﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using NTQOnlineExam.Services.EntityFW.Context;
using NTQOnlineExam.Services.EntityFW.Repository;
using NTQOnlineExam.Services.Infrastructure;
using NTQOnlineExam.Services.Infrastructure.Utility;
using NTQOnlineExam.Services.Models;
using NTQOnlineExam.Services.ReportService.Account;
using NTQOnlineExam.Services.ReportService.Section;

namespace NTQOnlineExam.Services.ReportService.Term
{
    public class TermReportService : ITermReportService
    {
        private readonly ICommandExecutor _commandExecutor;
        private readonly IGenericRepository<EntityFW.Entity.Term> _termGenericRepository;
        private readonly IAccountReportService _accountReportService;
        public TermReportService(ICommandExecutor commandExecutor, IGenericRepository<EntityFW.Entity.Term> termGenericRepository, IAccountReportService accountReportService)
        {
            _commandExecutor = commandExecutor;
            _termGenericRepository = termGenericRepository;
            _accountReportService = accountReportService;
        }

        public IList<TermDTO> GetTerms()
        {
            var termTable = DBCommand.DBCommand.CreateInstant().GetTermDbCommand();
            var result = ConvertDataTableToSectionDtos(termTable);
            return result;
        }

        private IList<TermDTO> ConvertDataTableToSectionDtos(DataTable dtTable)
        {
            var termDTOs = new List<TermDTO>();
            foreach (DataRow dtRow in dtTable.Rows)
            {
                var termDTO = new TermDTO();
                termDTO.TermId = (int)dtRow["TermId"];
                termDTO.TermName = dtRow["TermName"].ToString();
                termDTO.Description = dtRow["Description"].ToString();
                termDTO.Price = Convert.ToDecimal(dtRow["Price"]);
                termDTOs.Add(termDTO);
            }
            return termDTOs;
        }


        public SearchResult<TermDTO> GetTerms(int pageIndex, int pageSize, string sorting, int userId = 0)
        {
            var result = _commandExecutor.Execute(new GetTermDTOsDbCommand(pageIndex, pageSize, sorting));
            if (result == null || result.Count == 0) return null;
            var ids = result.Items.Select(x => x.TermId).ToList();
            var termsStatus = GetTermsStatus(ids, userId);
            if (termsStatus == null || termsStatus.Count == 0) return result;
            foreach (var termStatusDto in termsStatus)
            {
                var item = result.Items.FirstOrDefault(x => x.TermId == termStatusDto.TermId);
                if (item != null)
                {
                    item.ExpiredDate = termStatusDto.ExpiredDate;
                    item.IsPaid = termStatusDto.IsInPortfolio;
                }
            }
            return result;
        }


        public SearchResult<TermDTO> Search(SearchCriteria.TermSearchCriteria searchCriteria, int pageSize, int pageIndex)
        {
            return _commandExecutor.Execute(new GetTermDTOBySearchCriteriaDbCommand(searchCriteria, pageSize, pageIndex));
        }

        public TermDTO GetById(int termId, int userId = 0)
        {
            using (var context = new ExamOnlineDbContext())
            {
                var term = context.Terms.Find(termId); 
                var termDTO = Mapper.Map<EntityFW.Entity.Term, TermDTO>(term);
                var termsStatus = GetTermsStatus(new List<int> { termId }, userId);
                if (termsStatus == null || termsStatus.Count == 0) return termDTO;
                var status = termsStatus.FirstOrDefault(x => x.TermId == termDTO.TermId);
                if (status != null)
                {
                    termDTO.ExpiredDate = status.ExpiredDate;
                    termDTO.IsPaid = status.IsInPortfolio;
                }
                return termDTO;
                //return Mapper.Map<EntityFW.Entity.Term, TermDTO>(term);
            }
        }

        public SearchResult<TermDTO> GetTermsByYear(int? year, int pageIndex, int pageSize, int userId = 0)
        {
            var result = _commandExecutor.Execute(new GetTermDTOByYearDbCommand(pageSize, pageIndex, year));
            if (result == null || result.Count == 0) return new SearchResult<TermDTO>(new List<TermDTO>(), 0);
            var ids = result.Items.Select(x => x.TermId).ToList();
            var termsStatus = GetTermsStatus(ids, userId);
            if (termsStatus == null || termsStatus.Count == 0) return result;
            foreach (var termStatusDto in termsStatus)
            {
                var item = result.Items.FirstOrDefault(x => x.TermId == termStatusDto.TermId);
                if (item != null)
                {
                    item.ExpiredDate = termStatusDto.ExpiredDate;
                    item.IsPaid = termStatusDto.IsInPortfolio;
                }
            }
            return result;
        }

        public IList<TermStatusDTO> GetTermsStatus(IList<int> termIds, int userId)
        {
            if (userId <= 0) return new List<TermStatusDTO>();
            return _commandExecutor.Execute(new GetStatusOfTermListDbCommand(termIds, userId));
        }
    }
}